#include <iostream>
#include <cstring>
#include <vector>
#include <list>
#include <memory>
using namespace std;

template <typename T> using twin = pair<T, T>;  //模板别名

template <typename> class Blob; //声明，用于设置友元
template <typename> class BlobPtr;
// template <typename T> 
// bool operator==(const Blob<T>&, const Blob<T>&);

template <unsigned M, unsigned N>
inline int compare(const char (&p1)[M], const char (&p2)[N])
{
    return strcmp(p1, p2);
}

template <typename T>
class Blob{
    friend class BlobPtr<T>;  //这样写只有相同T的才是友元
    // template <typename T> friend class BlobPtr;  //这样任何T都是友元
    // friend bool operator==<T>(const Blob<T>&, const Blob<T>&);
public:
    typedef T value_type;
    typedef typename vector<T>::size_type st;
    Blob();
    Blob(initializer_list<T> l1);
    template <typename It>
    Blob(It b, It e);
    st size() const { return data->size(); }
    bool empty() const { return data->empty; }
    void push_back(const T &t) { data->push_back(t); }
    void push_back(T &&t) { data->push_back(move(t)); }
    void pop_back();
    T &back();
    T &operator[](st i);

private:
    shared_ptr<vector<T>> data;
    void check(st i, const string &msg) const;
};

template <typename T> 
Blob<T>::Blob():data(make_shared<vector<T>>()){}
template <typename T> 
Blob<T>::Blob(initializer_list<T> l1):data(make_shared<vector<T>>(l1)){}
template <typename T>
template <typename It> //成员在后
Blob<T>::Blob(It b, It e) : data(make_shared<vector<T>>(b, e)){}

template <typename T>
void Blob<T>::check(st i, const string &msg) const
{
    if(i >= data->size())
        throw out_of_range(msg);
}
template <typename T> 
T& Blob<T>::back()
{
    return data->size();
}
template <typename T> 
T& Blob<T>::operator[](st i)
{
    check(i, "too big");
    return (*data)[i];
}
template <typename T>
void Blob<T>::pop_back()
{
    check(0, "pop back on empty Blob");
    data->pop_back();
}

template <typename T>
class BlobPtr{
public:
    BlobPtr():curr(0){}
    BlobPtr(Blob<T> &a, size_t sz = 0) : wptr(a.data), curr(sz) {};
    T &operator*() const{
        auto p = check(curr, "dereference past end");
        return (*p)[curr];
    }
    BlobPtr &operator++();
    BlobPtr &operator--();
    
private:
    shared_ptr<vector<T>> check(size_t, const string &) const;
    weak_ptr<vector<T>> wptr;
    size_t curr;
};

template <typename T>
BlobPtr<T> &BlobPtr<T>::operator++()
{
    //在类模板的定义域内，可以不指定实参类型<T>
    BlobPtr ret = *this;
    ++*this;
    return ret;
}
template <typename T>
BlobPtr<T> &BlobPtr<T>::operator--()
{
    // 在类模板的定义域内，可以不指定实参类型<T>
    BlobPtr ret = *this;
    --*this;
    return ret;
}


int main(int argc, char const *argv[])
{
    twin<string> authors;
    // Blob<int> squares = {0, 1, 2, 3, 4};
    // Blob<string> article = {"a", "an", "and"};
    int ia[] = {0, 1, 2, 3};
    vector<long> vi = {0, 1, 2, 3};
    list<const char *> w = {"now", "is"};

    Blob<int> a2 (vi.begin(), vi.end());
    Blob<string> a3(w.begin(), w.end());
    cout << a3.size() << endl;
    return 0;
}
